/**
 * 数据库基类, 模块下面的 model 文件需要继承
 */
// const mongoose = global['mongoose'];
import paginateInterface from "../interface/paginateInterface";
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const fs  = require('fs');
import timestampPlugin from "../schema/plugins/timestamp";
mongoose.plugin(timestampPlugin);
/**
 * model 基类文件
 */
export default class BaseModel {
    /**
     * 设置属性
     */
    private _model = null;
    public M = null;
    public _schema = null;
    
    /**
     * 构造函数
     * @param table
     */
    constructor(table:string){
        if (new.target === BaseModel) {
            throw new Error('基类BaseModel不能实例化调用, 只能继承.');
        }
        
        if (!table) {
            throw new Error('基类BaseModel不能实例化调用, 只能继承.');
        }
        // 查找 对应 table 的 schema 文件
        let file = global['SCHEMA_PATH'] + table + '.js';
        if (!fs.existsSync(file)) {
            throw new Error(`schema file ${file} is not exists in app/schema/ ... `);
        }
        // this._schema = new Schema(require(global['SCHEMA_PATH'] + table + '.js'));
        this._schema = require(file);
        this.M = mongoose.model(`${table}`, this._schema);
    }
    
    /**
     * save document
     * @param params
     */
    async save(params : object){
        let instance = this.M;
        return await new instance(params).save();
    }
    
    /**
     * save document
     * @param params
     */
    async create(params: object){
        return await this.M.create(params);
    }
    
    /**
     * 查找所有的数据
     * @param conditions 
     */
    async find(conditions){
        return await this.M.find(conditions);
    }

    /**
     * 获取 model 的 schema 文件
     */
    get schema(){
        return this._schema;
    }

    /**
     * 分页方法
     * @param query 查询条件
     * @param paginate 分页参数
     * @param select 查询字段
     * @param sort  排序参数
     * @param populate 是否连表查询
     */
    async paginate(query: object, paginate: paginateInterface, select: object | string = {}, sort: object = { updated_at: -1 }, populate:object|string = null):Promise<object>{
        let resurnData = {
            page : paginate.page,
            page_size : paginate.page_size,
            total : await this.count(query),
            items: [],
        };
        let items: Array<object> = [];
        if (populate) {
            items = await this.M.find(query).select(select).sort(sort).skip((paginate.page - 1) * paginate.page_size).limit(paginate.page_size).populate(populate).exec();
        } else { 
            items = await this.M.find(query).select(select).sort(sort).skip((paginate.page - 1) * paginate.page_size).limit(paginate.page_size);
        }

        resurnData.items = items;
        return resurnData;
    }

    /**
     * 计算总数
     * @param query 
     */
    async count(query : object){
        return await this.M.countDocuments(query);
    }
}